package main

import (
	"github.com/valyala/fasthttp"
	//"strings"
	"api/http"
	"api/conf"
	"api/lib"
	"github.com/funlake/gopkg/utils/log"
	rawhttp "net/http"
	_ "net/http/pprof"
	"github.com/funlake/gopkg/utils"
	"api/types"
	"runtime/debug"
	"os"
	"encoding/json"
)
const MAX_THREAD = 50 * 1000
func init(){
	debug.SetMaxThreads(MAX_THREAD)
	if conf.GetConfig().GetEnv() != "prod" {
		go func() {
			rawhttp.ListenAndServe(":6060", nil)
		}()
	}
	println("=========================================")
	println("             _                           ")
	println("  __ _  __ _| |_ _____      ____ _ _   _ ")
	println(" / _` |/ _` | __/ _ \\ \\ /\\ / / _` | | | |")
	println(`| (_| | (_| | ||  __/\ V  V / (_| | |_| |
 \__, |\__,_|\__\___| \_/\_/ \__,_|\__, |
 |___/                             |___/
`)
	println("=========================================")
	//go metrics.Log(metrics.DefaultRegistry, 1 * time.Second, rawlog.New(os.Stderr, "metrics: ", rawlog.Lmicroseconds))
}
func main() {
	request := http.NewRequest()
	port := conf.GetConfig().GetEnvString("port","80")
	log.Success("listening on port %s",port)
	//utils.Print("hello")
	log.Error(fasthttp.ListenAndServe(":"+port, func(ctx *fasthttp.RequestCtx) {
		switch utils.ByteToStr(ctx.Path()) {
			case "/":
				hostname,_ := os.Hostname()
				http.ServeJson(ctx,200,"Welcome to api gateway of pqtest:"+hostname)
			case "/metrics":
				metricMap := http.Dispatcher.Metrics()
				var resultMap = make(map[string] interface{})
				metricMap.Range(func(key, value interface{}) bool {
					resultMap[key.(string)] = value
					return true
				})
				//metricMap.Load("workers")
				metrics,merr := json.Marshal(resultMap)
				if merr == nil{
					ctx.Write(metrics)
				}else{
					http.ServeJson(ctx,200,"Could not get metrics")
				}
		    case "/api-cleancache" :
				apiActionPermissionCheck(ctx, func() {
					cache := lib.NewCache()
					cache.Flush()
					http.ServeJson(ctx,200, "Local caches have been flushed")
				})
			case "/api-setrouting" :
				apiActionPermissionCheck(ctx, func() {
					//cache := lib.NewCache()
					//cache.Flush()
					http.ServeJson(ctx,200, "Ok")
				})
			default:
				proxyRequest(request, ctx)
		}
	}).Error())
}
func apiActionPermissionCheck(ctx *fasthttp.RequestCtx,fun func()) {
	act := ctx.Request.Header.Peek("api-call-token")
	if string(act) != "etcchebao2018" {
		http.ServeJson(ctx,403,"Permission denied")
	} else{
		fun()
	}
}

func proxyRequest(request *http.Request,ctx *fasthttp.RequestCtx){
	defer utils.RoutineRecover("Unexecpted error")
	proxyContext,proxyErr := types.NewProxyContext(ctx)
	if proxyErr != nil{
		http.ServeJson(ctx,conf.REQUEST_ROUTE_NOT_EXISTS,proxyErr.Error())
		return
	}
	flag, code, msg, _ := request.ProxyHttpRequest(proxyContext, ctx)
	if code >= 300 && code < 400 {
		ctx.Response.SetStatusCode(code)
	}
	if !flag {
		log.Error("Unexcepted response , %s -> code : %d,res : %s",proxyContext.Mapkey,code,msg)
		if code == conf.REQUEST_TIMEOUT{
			ctx.Response.SetStatusCode(502)
		}
		if code == conf.REQUEST_SERVICE_TEMPORARY_DOWN{
			ctx.Response.SetStatusCode(503)
		}
		http.ServeJson(ctx,code,msg)
		return
	}
	ctx.Write(utils.StrToByte(msg))
}